package com.itheima.health.filter;

import com.alibaba.fastjson.JSON;
import com.itheima.health.dao.PermissionDao;
import com.itheima.health.dao.RoleDao;
import com.itheima.health.entity.Result;
import com.itheima.health.pojo.Member;
import com.itheima.health.pojo.Role;
import com.itheima.health.pojo.User;
import com.itheima.health.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * @Created by PANG on 2/8/2022 上午11:55
 */
@Slf4j
@WebFilter("/*")
public class CompetenceFilter implements Filter {
    @Autowired
    private AntPathMatcher antPathMatcher;
    @Autowired
    private UserService userService;
    @Autowired
    private PermissionDao permissionDao;
    @Autowired
    private RoleDao roleDao;
    //权限表
    private HashMap<String,String> permissionMap = new HashMap<>();


    private String[] whiteList = {
            "/user/login",
            "/user/logout",
            "/common/**",
            "/mobile/**"
    };
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("初始化权限map");
         //初始化权限map
        initMap();
    }

    /**
     * 初始化权限map
     */
    public void initMap(){
        permissionMap.put("/checkitem/delete","CHECKITEM_DELETE");
        permissionMap.put("/checkitem/add","CHECKITEM_ADD");
        permissionMap.put("/checkitem/edit","CHECKITEM_EDIT");
        permissionMap.put("/checkitem/findPage","CHECKITEM_QUERY");
        permissionMap.put("/checkitem/findAll","CHECKITEM_QUERY");
        permissionMap.put("/checkgroup/delete","CHECKGROUP_DELETE");
        permissionMap.put("/checkgroup/add","CHECKGROUP_ADD");
        permissionMap.put("/checkgroup/edit","CHECKGROUP_EDIT");
        permissionMap.put("/checkgroup/findPage","CHECKGROUP_QUERY");
        permissionMap.put("/checkgroup/findAll","CHECKGROUP_QUERY");
        permissionMap.put("/setmeal/delete","SETMEAL_DELETE");
        permissionMap.put("/setmeal/add","SETMEAL_ADD");
        permissionMap.put("/setmeal/upload","SETMEAL_ADD");
        permissionMap.put("/setmeal/edit","SETMEAL_EDIT");
        permissionMap.put("/setmeal/findPage","SETMEAL_QUERY");
        permissionMap.put("/setmeal/findAll","SETMEAL_QUERY");
        permissionMap.put("/ordersetting/upload","ORDERSETTING");
        permissionMap.put("/ordersetting/editNumberByDate","ORDERSETTING");
        permissionMap.put("/report/**","REPORT_VIEW");
        permissionMap.put("/menu/add","MENU_ADD");
        permissionMap.put("/menu/delete","MENU_DELETE");
        permissionMap.put("/menu/edit","MENU_EDIT");
        permissionMap.put("/menu/findPage","MENU_QUERY");
        permissionMap.put("/menu/findAll","MENU_QUERY");
        permissionMap.put("/role/add","ROLE_ADD");
        permissionMap.put("/role/delete","ROLE_DELETE");
        permissionMap.put("/role/edit","ROLE_EDIT");
        permissionMap.put("/role/findPage","ROLE_QUERY");
        permissionMap.put("/role/findAll","ROLE_QUERY");
        permissionMap.put("/user/add","USER_ADD");
        permissionMap.put("/user/delete","USER_DELETE");
        permissionMap.put("/user/edit","USER_EDIT");
        permissionMap.put("/user/findPage","USER_QUERY");
        permissionMap.put("/user/findAll","USER_QUERY");
    }



    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //全部拦截
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        //判断白名单，是就放行
        String url = req.getRequestURI();
        log.info("白名单过滤...{}",url);
        if(isWhite(url)){
            log.info("已放行{}{}",url);
            filterChain.doFilter(req,resp);
            return;
        }
        //非白名单，判断是否会员
        Member member = (Member)req.getSession().getAttribute("member");
        //会员放行
        if(member!=null) filterChain.doFilter(req,resp);
        //不是会员，获取员工登录信息
        User user = (User)req.getSession().getAttribute("user");
        //用户未登录拦截
        if(user==null){
            resp.setContentType("application/json; charset=UTF-8");
            resp.getWriter().write(JSON.toJSONString(
            new Result(false,"用户未登录!")));
            return;
        }
        //已登录，判断当前是否该放行
        if(isDoFilter(url,user)){
            log.info("已放行{}+{}",user.getUsername(),url);
            filterChain.doFilter(req,resp);
        }else {
            log.info("无权限{}+{}",user.getUsername(),url);
            resp.setContentType("application/json; charset=UTF-8");
            resp.getWriter().write(JSON.toJSONString(
                    new Result(false,"用户无权限!")));
        }
    }

    /**
     * 是否放行当前请求
     * @param currentUrl
     * @param user
     * @return
     */
    private boolean isDoFilter(String currentUrl,User user){
        //判断当前访问url需要哪个权限
        String permission = whichPermission(currentUrl);
        log.info("申请访问{}+{}",currentUrl,permission);
        //无权限要求，谁都能访问
        if(permission==null) return true;

        //获取当前用户有哪些角色
        List<Role> roles = userService.getRoles(user);
        //获取这些角色的权限
        HashSet<String>   permissionSet = new HashSet<>();
        for (Role role : roles) {
            //去重
            permissionSet.addAll(permissionDao.getListByRoleId(role.getId()));
        }
        log.info("用户{}的权限列表{}",roles,permissionSet);
        //正确，获取到需要的权限，遍历hashset查看有无权限
        return permissionSet.contains(permission);
    }

    /**
     * 判断当前访问url需要哪个权限
     * @param currentUrl
     * @return
     */
    private String whichPermission(String currentUrl){
        for (String mapKey : permissionMap.keySet()) {
            if(antPathMatcher.match(mapKey,currentUrl)){
                  return permissionMap.get(mapKey);
            }
        }
        return null;
    }

    /**
     * 用来判断路径是否属于白名单
     * @param url
     * @return
     */
    private boolean isWhite(String url){
        for (String s : whiteList) {
            if(antPathMatcher.match(s,url)) return true;
        }
        return false;
    }

    @Override
    public void destroy() {

    }
}
